home *** CD-ROM | disk | FTP | other *** search
- { ASPI.TPU }
-
- { Andreas Schiffler, U of S, 1994 }
-
- { ASPI to SCSI-Tape (i.e. Exabyte) Interface Unit to provide most of the }
- { functions available for the EXB-8500 tape drive. }
-
- { 286/287 instructions enabled for assembler code }
- {$G+}
-
- Unit ASPI;
-
- Interface
-
- Uses Dos, Crt;
-
- Const
-
- { Communication with ASPI over a data-block (SRB): }
- { |---------64-------------|------6/10-------|--------- N ----------| }
- { ASPI-command SCSI-Command from Device (sense)
-
- { Field lengths }
- ASPIBlockLength = 64;
- CommandBlockLength = 6;
- SenseBlockLength = 29;
- SRBBlockLength = ASPIBlockLength+CommandBlockLength+SenseBlockLength+4;
-
- { Field locations }
- CommandLocation = ASPIBlockLength;
- SenseLocation = ASPIBlockLength+CommandBlockLength;
-
- { Local data buffer }
- DataBufferSize = 256;
-
- Type
- PDataBuffer = ^TDataBuffer;
- TDataBuffer = Array [0..(DataBufferSize-1)] of Byte;
-
- { These values are defined after a call to INQUIRY. }
- { }
- TapeInfo = Record
- Valid : Boolean;
- HostNumber : Byte;
- Target : Byte;
- Host : String[32];
- Device : String[16];
- Vendor : String[8];
- Product : String[16];
- Revision : String[4];
- Serial : String[10];
- End;
-
- { ERROR indicates any kind of status which requires attention. }
- { WRITE_PROTECTION_ON is only defined when ERROR is false.}
- { }
- TapeStatus = Record
- Error : Boolean;
- ASPI : String[60];
- Host : String[60];
- Target : String[60];
- Sense : String[60];
- SenseExt : String[60];
- FilemarkDetected : Boolean;
- TapeNotPresent : Boolean;
- BeginningOfTape : Boolean;
- EndOfTape : Boolean;
- WriteProtectOn : Boolean;
- End;
-
- SRBType = Array [0..(SRBBlockLength-1)] Of Byte;
-
- PASPITape = ^ASPITape;
- ASPITape = Object
- SRB : SRBType;
- HSeg_Data,
- LSeg_Data,
- HOfs_Data,
- LOfs_Data : Byte;
- SenseStart : Byte;
- DataBuffer : PDataBuffer;
- TarBlock : Byte;
- Info : TapeInfo;
- Status : TapeStatus;
-
- Constructor Init (TargetNumber : Byte);
- Destructor Done;
- Procedure CallASPI;
- Procedure Inquiry;
- Procedure RequestSense;
- Procedure TestUnitReady;
- Procedure ParseStatus;
- Procedure ModeSelect(BufferSize : Word);
- Procedure ReadData(Buffer : Pointer; BufferSize : Word);
- Procedure WriteData(Buffer : Pointer; BufferSize : Word);
- Function TapePosition : Longint;
- Procedure LocateTape (Location : Longint);
- Procedure ASPIReset;
- Procedure WriteFilemark (Number : Byte);
- Procedure SpaceFilemark (Spacing : Longint);
- Procedure GotoEnd;
- Procedure Rewind;
- Procedure Unload;
- Procedure Load;
- Procedure Erase;
- End;
-
- Implementation
-
- Var
- GlobalSRB : SRBType; { THE ASPI Command Block }
- LockSRB : Boolean; { Sync. flag for multiple objects }
-
- { Utility routines }
- { ================ }
-
- { ASPITape routines }
- { ================= }
-
- Constructor ASPITape.Init (TargetNumber : Byte);
-
- Begin
- { Initialize variables }
- Info.Valid := False;
- Info.Target := TargetNumber;
- Info.HostNumber := 0;
- Info.Host := '?';
- Info.Vendor := '?';
- Info.Product := '?';
- Info.Revision := '?';
- Info.Serial := '?';
- Info.Device := '?';
- Status.Error := False;
- Status.ASPI := '?';
- Status.Host := '?';
- Status.Target := '?';
- Status.Sense := '?';
- Status.SenseExt := '?';
- Status.FilemarkDetected := False;
- Status.TapeNotPresent := False;
- Status.BeginningOfTape := False;
- Status.EndOfTape := False;
- Status.WriteProtectOn := False;
-
- New(DataBuffer); { Create and Init data buffer }
- LSeg_Data := Lo(Seg(DataBuffer^));
- HSeg_Data := Hi(Seg(DataBuffer^));
- LOfs_Data := Lo(Ofs(DataBuffer^));
- HOfs_Data := Hi(Ofs(DataBuffer^));
- FillChar (DataBuffer^[0],DataBufferSize,0);
- End;
-
- Destructor ASPITape.Done;
- Begin
- Dispose (DataBuffer);
- End;
-
- Procedure ASPITape.CallASPI;
- Const
- Message : Array [0..9] of Char = ('S','C','S','I','M','G','R','$',#0,#0);
- Var
- ASPIEntry : Array [0..3] of Byte;
- Timeout : Longint;
- Manager : Byte;
- Begin
- { Set Manager flag }
- Manager := 0;
- { Wait until GlobalSRB gets unlocked. }
- While LockSRB Do ;
- { Lock SRB transfer to global data and execute. }
- LockSRB := True;
- Move(SRB,GlobalSRB,SizeOf(SRBType));
- Asm
- Push DS
-
- mov ax,$3d00
- lea dx,Message
- int $21
- jc @NoManager
-
- push ax
- mov bx,ax
- mov ax,$4402
- lea dx,ASPIEntry
- mov cx,4
- int $21
-
- mov ah,$3e
- pop bx
- int $21
-
- push ds
- lea bx,[GlobalSRB]
- push bx
- lea bx,ASPIEntry
- call dword ptr [bx]
- add sp,4
- mov al,1;
- mov manager,al
-
- @NoManager:
- Pop DS
- End;
- { Check if a ASPI Manager was present }
- IF (Manager=1) Then Begin
- { Wait for command to finish - timeout after a 4 hours. }
- { This will give time for slow commands liek ERASE to finish. }
- Timeout := 0;
- Repeat
- INC(Timeout);
- Delay (10);
- Until ((GlobalSRB[1]<>0) OR (Timeout=4*60*60*100));
- If Timeout=4*60*60*100 Then GlobalSRB[1]:=$FF; { report Timeout Error }
- End Else Begin
- GlobalSRB[1]:=$FE; { No ASPI Manager Error }
- Info.Valid := False;
- End;
- { Transfer to local buffer and unlock. }
- Move (GlobalSRB,SRB,SizeOf(SRBType));
- LockSRB := False;
- { Check for request sense command and any errors from that }
- If (SRB[0]=2) AND (SRB[64]=$03) AND ((DataBuffer^[2] AND $0F)<>0) Then Begin
- { Transfer data to SRB and set flag to check }
- SRB[25] := $02;
- Move (DataBuffer^,SRB[70],29);
- End;
- { Determine Sense Location }
- SenseStart := 64+SRB[23];
- { Determine error status from ASPI, Host and Sense area }
- Status.Error := (SRB[1]<>1) OR (SRB[24]<>0) OR (SRB[25]<>0) OR ((SRB[SenseStart+2] AND $0F)<>0);
- End;
-
- { Call this whenever the ERROR is set to fill the STATUS fields. }
- { }
- Procedure ASPITape.ParseStatus;
- Begin
- If SRB[1]=$FE Then Begin
- Status.ASPI := 'No ASPI-Manager present';
- Status.Host := '?';
- Status.Target := '?';
- Status.Sense := '?';
- Status.SenseExt := '?';
- Status.FilemarkDetected := False;
- Status.TapeNotPresent := False;
- Status.BeginningOfTape := False;
- Status.WriteProtectOn := False;
- Status.EndOfTape := False;
- End Else Begin
- { Get all the information }
- RequestSense;
- { Determine status }
- Case SRB[1] of
- 0: Status.ASPI := 'SCSI request in progress';
- 1: Status.ASPI := 'SCSI request completed without error';
- 2: Status.ASPI := 'SCSI request aborted by host';
- 4: Status.ASPI := 'SCSI request completed with error';
- $80: Status.ASPI := 'SCSI request invalid';
- $81: Status.ASPI := 'Invalid host adapter number';
- $82: Status.ASPI := 'SCSI adapter not installed';
- $FF: Status.ASPI := 'SCSI request in progress, timeout';
- End;
- Case SRB[24] of
- $00: Status.Host := 'Host adapter did not detect any error';
- $11: Status.Host := 'Selection timeout';
- $12: Status.Host := 'Data overrun/underrun';
- $13: Status.Host := 'Unexpected bus free';
- $14: Status.Host := 'Target bus phase sequence failure';
- End;
- Case SRB[25] of
- $00: Status.Target := 'No/Good target status';
- $02: Status.Target := 'Sense data available';
- $04: Status.Target := 'Condition met';
- $08: Status.Target := 'Specified target busy';
- $14: Status.Target := 'Intermediate condition met';
- $18: Status.Target := 'Reservation conflict';
- $22: Status.Target := 'Command terminated';
- $28: Status.Target := 'Queue full';
- End;
- If SRB[25]=$02 Then Begin
- { Sense available }
- Case (SRB[SenseStart+2] AND $0F) of
- 0: Begin
- Status.Sense := 'No Sense';
- Case SRB[82] of
- $00: Case SRB[83] of
- $01: Status.SenseExt := 'Filemark encountered during read';
- $02: Status.SenseExt := 'LEOT encountered';
- $04: Status.SenseExt := 'LBOT detected';
- End;
- $3b: Status.SenseExt := 'Tape position error at beginning';
- End;
- End;
- 1: Begin
- Status.Sense := 'Recovered Error';
- Status.SenseExt := '';
- End;
- 2: Begin
- Status.Sense := 'Not Ready';
- Case SRB[SenseStart+12] of
- $04: Case SRB[SenseStart+13] of
- $00: Status.SenseExt := 'Tape not present';
- $01: Status.SenseExt := 'Tape loading or rewinding';
- $02: Status.SenseExt := 'Tape motion command required';
- $03: Status.SenseExt := 'Unrecoverable hardware error';
- End;
- $3A: Status.SenseExt := 'Tape not present';
- End;
- End;
- 3: Begin
- Status.Sense := 'Medium Error';
- Case SRB[SenseStart+12] of
- $3b: Case SRB[SenseStart+13] of
- $00: Status.SenseExt := 'Position error';
- $02: Status.SenseExt := 'Position error at end';
- End;
- $00: Status.SenseExt := 'Undetermined error';
- $03: Status.SenseExt := 'Excessive write errors';
- $09: Status.SenseExt := 'Tracking error';
- $0C: Status.SenseExt := 'Hard write error';
- $11: Status.SenseExt := 'Hard read error';
- End;
- End;
- 4: Begin
- Status.Sense := 'Hardware Error';
- Case SRB[SenseStart+12] of
- $40: Case SRB[83] of
- $80: Status.SenseExt := 'DPATH error';
- $81: Status.SenseExt := 'DPATH underrun';
- End;
- $00: Status.SenseExt := 'Undetermined';
- $09: Status.SenseExt := 'Track follow error';
- $44: Status.SenseExt := 'Internal failure/Software hang';
- End;
- End;
- 5: Begin
- Status.Sense := 'Illegal Request';
- Case SRB[SenseStart+12] of
- $1A: Status.SenseExt := 'Parameter list length error';
- $20: Status.SenseExt := 'Illegal CDB code';
- $24: Status.SenseExt := 'Invalid CDB field';
- $25: Status.SenseExt := 'LUN not supported';
- $26: Status.SenseExt := 'Invalid parameter';
- $3D: Status.SenseExt := 'LUN invalid';
- $81: Status.SenseExt := 'Fixed mode mismatch';
- End;
- End;
- 6: Begin
- Status.Sense := 'Unit Attention';
- Case SRB[SenseStart+12] of
- $28: Status.SenseExt := 'Media has been changed';
- $29: Status.SenseExt := 'Reset has occured';
- $2A: Status.SenseExt := 'Mode select has been changed';
- $3F: Status.SenseExt := 'New microcode loaded';
- End;
- End;
- 7: Begin
- Status.Sense := 'Data Protect';
- Status.SenseExt := 'The tape is write protected';
- End;
- 8: Begin
- Status.Sense := 'Blank Check';
- Status.SenseExt := 'End of data encountered on read';
- End;
- 9: Begin
- Status.Sense := 'EXABYTE specific error';
- Status.SenseExt := '';
- End;
- 10: Begin
- Status.Sense := 'Copy Aborted';
- Status.SenseExt := '';
- End;
- 11: Begin
- Status.Sense := 'Aborted Command';
- Case SRB[SenseStart+12] of
- $45: Status.SenseExt := 'Reselect failed';
- $47: Status.SenseExt := 'SCSI bus failure during write';
- $48: Status.SenseExt := 'Initiator detected error';
- $49: Status.SenseExt := 'Invalid message recieved';
- End;
- End;
- 13: Begin
- Status.Sense := 'Volume Overflow';
- Status.SenseExt := 'PEOT encountered during write';
- End;
- End;
- { Set booleans }
- Status.FilemarkDetected := ((SRB[SenseStart+ 2] AND $80)<>0);
- Status.TapeNotPresent := ((SRB[SenseStart+19] AND $02)<>0);
- Status.BeginningOfTape := ((SRB[SenseStart+19] AND $01)<>0);
- Status.WriteProtectOn := ((SRB[SenseStart+20] AND $20)<>0);
- Status.EndOfTape := ((SRB[SenseStart+21] AND $04)<>0);
- End Else Begin
- { Sense not available }
- Status.Sense := '';
- Status.SenseExt := '';
- End;
- End;
- End;
-
- { Used by ParseStatus. }
- { }
- Procedure ASPITape.RequestSense;
- Begin
- { ASPI Setup for sense inquiry }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[10]:=29;
- SRB[15]:=LOfs_Data;
- SRB[16]:=HOfs_Data;
- SRB[17]:=LSeg_Data;
- SRB[18]:=HSeg_Data;
- SRB[23]:=6;
- SRB[64]:=$03;
- SRB[68]:=29;
- { Execute }
- CallASPI;
- End;
-
- { Determine host and tape parameters, thus initializing the INFO field. }
- { }
- Procedure ASPITape.Inquiry;
- Begin
- { ASPI Setup for host inquiry }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=0;
- SRB[ 8]:=Info.Target;
- { Execute }
- CallASPI;
- If Status.Error Then ParseStatus;
- { Extract information }
- Move (SRB[10],Info.Host[1],32);
- Info.Host[0]:=Chr(32);
- Info.HostNumber := SRB[8];
- { Setup for device inquiry }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=1;
- SRB[ 8]:=Info.Target;
- { Execute }
- CallASPI;
- { Extract Information }
- Info.Valid := False;
- If Status.Error Then Begin
- ParseStatus;
- Info.Device := 'Unknown';
- End Else
- Case SRB[10] of
- 0: Begin Info.Device:='Disk'; Info.Valid := True; End;
- 1: Begin Info.Device:='Tape'; Info.Valid := True; End;
- 2: Begin Info.Device:='Printer'; Info.Valid := True; End;
- 3: Begin Info.Device:='Processor'; Info.Valid := True; End;
- 4: Begin Info.Device:='WORM'; Info.Valid := True; End;
- 5: Begin Info.Device:='CD-ROM'; Info.Valid := True; End;
- 6: Begin Info.Device:='Scanner'; Info.Valid := True; End;
- 7: Begin Info.Device:='Optical Memory'; Info.Valid := True; End;
- 8: Begin Info.Device:='Medium Changer'; Info.Valid := True; End;
- 9: Begin Info.Device:='Communication'; Info.Valid := True; End;
- Else
- Info.Device := 'Unknown';
- End;
- If Info.Valid Then Begin
- { ASPI Setup for specific inquiry }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[10]:=106;
- SRB[15]:=LOfs_Data;
- SRB[16]:=HOfs_Data;
- SRB[17]:=LSeg_Data;
- SRB[18]:=HSeg_Data;
- SRB[23]:=6;
- SRB[64]:=$12;
- SRB[68]:=106;
- { Execute }
- CallASPI;
- { Extract product information to Pascal strings }
- Move (DataBuffer^[8],Info.Vendor[1],8);
- Info.Vendor[0]:=#8;
- Move (DataBuffer^[16],Info.Product[1],16);
- Info.Product[0]:=#16;
- Move (DataBuffer^[32],Info.Revision[1],4);
- Info.Revision[0]:=#4;
- Move (DataBuffer^[96],Info.Serial[1],10);
- Info.Serial[0]:=#10;
- End;
- End;
-
- { This routine is used to prepare the tape drive for a "good" status.}
- { Keep calling this routine until ERROR is false. }
- { }
- Procedure ASPITape.TestUnitReady;
- Begin
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[23]:=6;
- SRB[64]:=0;
- { Execute }
- CallASPI;
- End;
-
- { Set the tape with current 'BlockSize' and use buffered-mode writes. }
- { }
- Procedure ASPITape.ModeSelect (BufferSize : Word);
- Begin
- { ASPI Setup for Mode Select }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[10]:=12;
- SRB[15]:=LOfs_Data;
- SRB[16]:=HOfs_Data;
- SRB[17]:=LSeg_Data;
- SRB[18]:=HSeg_Data;
- SRB[23]:=6;
- SRB[64]:=$15;
- SRB[65]:=$10;
- SRB[68]:=12;
- FillChar (DataBuffer^[0],12,0);
- DataBuffer^[2]:=$10; { Buffered mode }
- DataBuffer^[3]:=8;
- DataBuffer^[10]:=Hi(BufferSize);
- DataBuffer^[11]:=Lo(BufferSize);
- { Execute }
- CallASPI;
- End;
-
- { Write the block in 'Buffer' to tape. }
- { }
- Procedure ASPITape.WriteData (Buffer : Pointer; BufferSize : Word);
- Begin
- { ASPI Setup for Block Write }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[10]:=Lo(BufferSize);
- SRB[11]:=Hi(BufferSize);
- SRB[15]:=Lo(Ofs(Buffer^));
- SRB[16]:=Hi(Ofs(Buffer^));
- SRB[17]:=Lo(Seg(Buffer^));
- SRB[18]:=Hi(Seg(Buffer^));
- SRB[23]:=6;
-
- SRB[64]:=$0A;
- SRB[65]:=$01;
- SRB[68]:=1; { Write one block of size set in MODE SELECT }
- { Execute }
- CallASPI;
- { Reset TarBlock count }
- TarBlock := 0;
- End;
-
- { Reads the next block of 'BufferSize' and stores it in 'Buffer'. }
- { }
- Procedure ASPITape.ReadData(Buffer : Pointer; BufferSize : Word);
- Begin
- { ASPI Setup for Block Read }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[10]:=Lo(BufferSize);
- SRB[11]:=Hi(BufferSize);
- SRB[15]:=Lo(Ofs(Buffer^));
- SRB[16]:=Hi(Ofs(Buffer^));
- SRB[17]:=Lo(Seg(Buffer^));
- SRB[18]:=Hi(Seg(Buffer^));
- SRB[23]:=6;
-
- SRB[64]:=$08;
- SRB[65]:=$01;
- SRB[68]:=1; { Read one block of size set in MODE SELECT }
- { Execute }
- CallASPI;
- End;
-
- { Returns tape position in terms of logical blocks. }
- { }
- Function ASPITape.TapePosition : Longint;
- Type
- B4 = Array [0..4] Of Byte;
- Var
- L : Longint;
- LA : B4 Absolute L;
- Begin
- { ASPI Setup for Position Inquiry }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[10]:=20;
- SRB[15]:=LOfs_Data;
- SRB[16]:=HOfs_Data;
- SRB[17]:=LSeg_Data;
- SRB[18]:=HSeg_Data;
- SRB[23]:=10;
-
- SRB[64]:=$34;
- { Execute }
- CallASPI;
- { Extract Information }
- If ((DataBuffer^[0] And 4)<>0) Then
- TapePosition := -1 { Position unknown }
- Else Begin
- LA[0] := DataBuffer^[7];
- LA[1] := DataBuffer^[6];
- LA[2] := DataBuffer^[5];
- LA[3] := DataBuffer^[4];
- TapePosition := L;
- End;
- End;
-
- { Locate to a specific logical block. Any direction works. }
- { }
- Procedure ASPITape.LocateTape (Location : Longint);
- Begin
- { ASPI Setup for Set Position }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[23]:=10;
-
- SRB[64]:=$2B;
- SRB[67]:= ((Location SHR 24) AND $8F);
- SRB[68]:= ((Location SHR 16) AND $FF);
- SRB[69]:= ((Location SHR 8) AND $FF);
- SRB[70]:= (Location And $FF);
- { Execute }
- CallASPI;
- End;
-
- { Resets ASPI and the device connected to it. }
- { Causes a rewind. }
- { }
- Procedure ASPITape.ASPIReset;
- Begin
- { ASPI Setup for Reset }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=4;
- SRB[ 8]:=Info.Target;
-
- { Execute }
- CallASPI;
- End;
-
- { Write 'Number' filemarks to the tape }
- { }
- Procedure ASPITape.WriteFilemark (Number : Byte);
- Begin
- { ASPI Setup for Write Filemark }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[23]:=6;
-
- SRB[64]:=$10;
- SRB[68]:=Number;
-
- { Execute }
- CallASPI;
- End;
-
- { Space over 'Spacing' filemarks }
- { }
- Procedure ASPITape.SpaceFilemark (Spacing : Longint);
- Begin
- { ASPI Setup for Space Filemark }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[23]:=6;
-
- SRB[64]:=$11;
- SRB[65]:=1;
- SRB[66]:=((Spacing SHR 16) AND $FF);
- SRB[67]:=((Spacing SHR 8) AND $FF);
- SRB[68]:=(Spacing AND $FF);
-
- { Execute }
- CallASPI;
- End;
-
- { Set the tape to the 'End of Data'-position }
- { }
- Procedure ASPITape.GotoEnd;
- Begin
- { ASPI Setup for Spacing to EOD }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[23]:=6;
-
- SRB[64]:=$11;
- SRB[65]:=3;
-
- { Execute }
- CallASPI;
- End;
-
- { Rewinds the tape to the begining. }
- { }
- Procedure ASPITape.Rewind;
- Begin
- { ASPI Setup for Rewind }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[23]:=6;
-
- SRB[64]:=$01;
-
- { Execute }
- CallASPI;
- End;
-
- Procedure ASPITape.Unload;
- Begin
- { ASPI Setup for Unload }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[23]:=6;
-
- SRB[64]:=$1B;
- SRB[68]:=0;
-
- { Execute }
- CallASPI;
- End;
-
- Procedure ASPITape.Erase;
- Begin
- { ASPI Setup for Erase }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[23]:=6;
-
- SRB[64]:=$19;
- SRB[65]:=1;
-
- { Execute }
- CallASPI;
- End;
-
- Procedure ASPITape.Load;
- Begin
- { ASPI Setup for Load }
- FillChar (SRB,SizeOf(SRB),0);
- SRB[ 0]:=2;
- SRB[ 8]:=Info.Target;
- SRB[23]:=6;
-
- SRB[64]:=$1B;
- SRB[68]:=1;
-
- { Execute }
- CallASPI;
- End;
-
- { ============================================================ }
-
- { Initialisation code }
- Begin
- LockSRB := False;
- End.
-